package org.iabako.server.dao.report;

import org.iabako.server.serviceimpl.security.SessionUser;
import org.iabako.server.tools.BundleMessages;
import org.iabako.shared.dto.FinancesBalance;
import org.iabako.shared.entity.business.Sale;
import org.iabako.shared.entity.user.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by jose on 27/01/15.
 */

@Repository("reportDAO")
public abstract class AbstractReportDAO {

    @PersistenceContext(unitName = "MyPersistenceUnit")
    protected EntityManager entityManager;

    @Autowired
    BundleMessages messages;
    @Autowired
    SessionUser sessionUser;

    protected User getSessionUser() {
        return sessionUser != null ? sessionUser.getUser() : null;
    }

    protected void addIncomeToMapByEntity(Map<Object, FinancesBalance> mapByEntity, List<Object[]> result, boolean addPayed) {
        addResultToMapByEntity(mapByEntity, result, null, addPayed, true);
    }

    protected void addInstallmentToMapByEntity(Map<Object, FinancesBalance> mapByEntity, List<Object[]> result, Date financesBalanceDate, boolean addPayed) {
        addResultToMapByEntity(mapByEntity, result, financesBalanceDate, addPayed, true);
    }

    protected void addExpenseToMapByEntity(Map<Object, FinancesBalance> mapByEntity, List<Object[]> result, boolean addPayed) {
        addResultToMapByEntity(mapByEntity, result, null, addPayed, false);
    }

    protected void addResultToMapByEntity(Map<Object, FinancesBalance> mapByEntity, List<Object[]> result, Date financesBalanceDate, boolean addPayed, boolean sale) {
        for (Object[] o : result) {
            Object entity = o[0];
            FinancesBalance financesBalance;
            if (mapByEntity.get(entity) == null) {
                mapByEntity.put(entity, new FinancesBalance());
            }
            financesBalance = mapByEntity.get(entity);
            if (sale) {
                if (addPayed) {
                    financesBalance.addSalesPayed((Double) o[1]);
                } else {
                    financesBalance.addSalesReceivable((Double) o[1]);
                }
            } else {
                if (addPayed) {
                    financesBalance.addExpensesPayed((Double) o[1]);
                } else {
                    financesBalance.addExpensePayable((Double) o[1]);
                }
            }

            financesBalance.setFinanceBalanceDate(financesBalanceDate);
        }
    }

    //TODO make a calculated price value in sale for this report and for sale search form
    public Double getPriceForSale(Sale sale) {
        String query = "SELECT SUM(p.amount) FROM Payment p WHERE p.sale = :sale";
        Double payed = (Double) entityManager.createQuery(query).setParameter("sale", sale).getSingleResult();
        payed = payed == null ? 0D : payed;
        query = "SELECT SUM(i.amount) FROM Installment i WHERE i.sale = :sale";
        Double receivable = (Double) entityManager.createQuery(query).setParameter("sale", sale).getSingleResult();
        receivable = receivable == null ? 0D : receivable;

        return payed + receivable;
    }
}
